#include <QtCore/QLatin1String> // for QLatin1String
#include <QtCore/QString> // for QString, operator+, operator==, operator!=
#include <QtCore/QTextCodec> // for QTextCodec
+#include <QtCore/QTextEncoder> // for QTextEncoder
#include <QtCore/QTime> // for QTime
#include <QtCore/Qt> // for CaseInsensitive, UTC
#include <QtCore/QtGlobal> // for qPrintable, uint, foreach
if (bytes_per_char == 1) {
qba = buf.toUtf8();
} else {
- qba = utf16le_codec->fromUnicode(buf);
+ QTextEncoder* encoder = utf16le_codec->makeEncoder(QTextCodec::IgnoreHeader);
+ qba = encoder->fromUnicode(buf);
+ delete encoder;
}
int len = qba.size();
gbfputint32(len, file_out);
static Lowranceusr4Timestamp
lowranceusr4_jd_from_timestamp(gpsbabel::DateTime qdt)
{
- QDateTime jdt = qdt.toUTC().addSecs(-60 * 60 * 12);
+ QDateTime jdt = qdt.toUTC();
unsigned int jd_number = jdt.date().toJulianDay();
QTime jd_time = jdt.time();
unsigned int msecs = (((((jd_time.hour() * 60) + jd_time.minute()) * 60) + jd_time.second()) * 1000) + jd_time.msec();
return Lowranceusr4Timestamp(jd_number, msecs);
}
-
-const QString
-lowranceusr_find_desc_from_icon_number(const int icon)
+template <typename T>
+static QString lowranceusr_common_find_desc_from_icon_number(const int icon, const T icon_value_table[])
{
- for (const lowranceusr_icon_mapping_t* i = lowranceusr_icon_value_table; i->icon; i++) {
+ for (const T* i = icon_value_table; i->icon; i++) {
if (icon == i->value) {
return i->icon;
}
return QString("icon-%1").arg(icon);
}
-static int
-lowranceusr_find_icon_number_from_desc(const QString& desc)
+template <typename T>
+static int lowranceusr_common_find_icon_number_from_desc(const QString& desc, const T icon_value_table[], const int def_icon)
{
if (desc.isNull()) {
- return DEF_ICON;
+ return def_icon;
}
/*
* If we were given a numeric icon number as a description
* (i.e. 8255), just return that.
+ * Also return the icon number for descriptions of "icon-"
+ * followed by a numeric icon number.
*/
- int n = desc.toInt();
+ int n = desc.mid(desc.startsWith("icon-") ? 5 : 0).toInt();
if (n) {
return n;
}
- for (const lowranceusr_icon_mapping_t* i = lowranceusr_icon_value_table; i->icon; i++) {
+ for (const T* i = icon_value_table; i->icon; i++) {
if (desc.compare(i->icon,Qt::CaseInsensitive) == 0) {
return i->value;
}
}
- return DEF_ICON;
+ return def_icon;
}
-const QString
-lowranceusr4_find_desc_from_icon_number(const int icon)
+static QString
+lowranceusr_find_desc_from_icon_number(const int icon)
{
- for (const lowranceusr4_icon_mapping_t* i = lowranceusr4_icon_value_table; i->icon; i++) {
- if (icon == i->value) {
- return i->icon;
- }
- }
-
- // Didn't find it in table, default to leave it as the number found
- return QString("icon-%1").arg(icon);
+ return lowranceusr_common_find_desc_from_icon_number(icon, lowranceusr_icon_value_table);
}
static int
-lowranceusr4_find_icon_number_from_desc(const QString& desc)
+lowranceusr_find_icon_number_from_desc(const QString& desc)
{
- if (desc.isNull()) {
- return DEF_USR4_ICON;
- }
-
- /*
- * If we were given a numeric icon number as a description
- * (i.e. 8255), just return that.
- */
- int n = desc.toInt();
- if (n) {
- return n;
- }
+ return lowranceusr_common_find_icon_number_from_desc(desc, lowranceusr_icon_value_table, DEF_ICON);
+}
- for (const lowranceusr4_icon_mapping_t* i = lowranceusr4_icon_value_table; i->icon; i++) {
- if (desc.compare(i->icon,Qt::CaseInsensitive) == 0) {
- return i->value;
- }
- }
+static QString
+lowranceusr4_find_desc_from_icon_number(const int icon)
+{
+ return lowranceusr_common_find_desc_from_icon_number(icon, lowranceusr4_icon_value_table);
+}
- return DEF_USR4_ICON;
+static int
+lowranceusr4_find_icon_number_from_desc(const QString& desc)
+{
+ return lowranceusr_common_find_icon_number_from_desc(desc, lowranceusr4_icon_value_table, DEF_USR4_ICON);
}
-const char *
+static const char *
lowranceusr4_find_color_from_icon_number_plus_color_index(const int icon, const int index)
{
for (const lowranceusr4_icon_mapping_t* i = lowranceusr4_icon_value_table; i->icon; i++) {
static long
lon_deg_to_mm(double x)
{
- return (long)(x * SEMIMINOR * DEGREESTORADIANS);
+ return round(x * SEMIMINOR * DEGREESTORADIANS);
}
static long
lat_deg_to_mm(double x)
{
- return (long)(SEMIMINOR * log(tan((x * DEGREESTORADIANS + M_PI / 2.0) / 2.0)));
+ return round(SEMIMINOR * log(tan((x * DEGREESTORADIANS + M_PI / 2.0) / 2.0)));
}
static void
lowranceusr4_waypt_disp(const Waypoint* wpt)
{
+ lowranceusr4_fsdata* fs = (lowranceusr4_fsdata*) fs_chain_find(wpt->fs, FS_LOWRANCEUSR4);
+
/* UID unit number */
if (opt_serialnum_i > 0) {
gbfputint32(opt_serialnum_i, file_out); // use option serial number if specified
- } else if (wpt->fs != nullptr) {
- gbfputint32(((lowranceusr4_fsdata*)(wpt->fs))->uid_unit, file_out); // else use serial number from input if valid
+ } else if (fs != nullptr) {
+ gbfputint32(fs->uid_unit, file_out); // else use serial number from input if valid
} else {
gbfputint32(0, file_out); // else Write Serial Number = 0
}
ColorId = 0; // default
} else {
SymbolId = lowranceusr4_find_icon_number_from_desc(wpt->icon_descr);
- if (wpt->fs != nullptr) {
- ColorId = lowranceusr4_find_index_from_icon_desc_and_color_desc(wpt->icon_descr, ((lowranceusr4_fsdata*)(wpt->fs))->color_desc);
+ if (fs != nullptr) {
+ ColorId = lowranceusr4_find_index_from_icon_desc_and_color_desc(wpt->icon_descr, fs->color_desc);
} else {
ColorId = DEF_USR4_COLOR; // default
}
gbfputc(0, file_out);
/* Depth in feet */
- if (wpt->fs != nullptr) {
- gbfputint32(((lowranceusr4_fsdata*)(wpt->fs))->depth, file_out);
+ if (fs != nullptr) {
+ gbfputint32(fs->depth, file_out);
} else {
gbfputint32(0, file_out); // zero seems to indicate no depth
}
route_uid, qPrintable(rte->rte_name), rte->rte_waypt_ct);
}
+ lowranceusr4_fsdata* fs = (lowranceusr4_fsdata*) fs_chain_find(rte->fs, FS_LOWRANCEUSR4);
+
/* UID unit number */
if (opt_serialnum_i > 0) {
gbfputint32(opt_serialnum_i, file_out); // use option serial number if specified
- } else if (rte->fs != nullptr) {
- gbfputint32(((lowranceusr4_fsdata*)(rte->fs))->uid_unit, file_out); // else use serial number from input if valid
+ } else if (fs != nullptr) {
+ gbfputint32(fs->uid_unit, file_out); // else use serial number from input if valid
} else {
gbfputint32(0, file_out); // else Write Serial Number = 0
}
for (int i = 0; i < waypt_table_ct; i++) {
Waypoint* cmp = waypt_table[i];
if (cmp->shortname == wpt->shortname) {
- lowranceusr4_fsdata* fsdata = (lowranceusr4_fsdata*)cmp->fs;
- gbfputint32(fsdata->uid_unit, file_out); // serial number from input if valid
+ lowranceusr4_fsdata* fs = (lowranceusr4_fsdata*) fs_chain_find(cmp->fs, FS_LOWRANCEUSR4);
+
+ if (opt_serialnum_i > 0) {
+ gbfputint32(opt_serialnum_i, file_out); // use option serial number if specified
+ } else if (fs != nullptr) {
+ gbfputint32(fs->uid_unit, file_out); // else use serial number from input if valid
+ } else {
+ gbfputint32(0, file_out); // else Write Serial Number = 0
+ }
gbfputint32(i, file_out); // Sequence Low
gbfputint32(0, file_out); // Sequence High
if (global_opts.debug_level > 1) {
/* Mysterious "data count" and "data type" stuff */
gbfputint32(0, file_out);
- gbfputc(0, file_out);
- gbfputc(0, file_out);
- gbfputc(0, file_out);
+// /* If we hadn't forced the count to zero we would need something like: */
+// for (int i=0; i< attr_count; ++i) {
+// gbfputc(0, file_out);
+// }
/* Trackpoint count */
gbfputint32(trail->rte_waypt_ct, file_out);
#
# Lowrance USR
# ============
-#
+#
# Binary data format, and slightly lossy because of the math to
# convert lat/long.
#
# Trail 'Trail 1' conains 0 points, Trail 'Bull Run' contains 97 points in a
# single section, Trail 'Hike' contains 198 points in a single section.
#
-# lowrance-enchilada.usr USR version 2 format file.
+# lowrance-enchilada.usr USR version 2 format file.
# Used to validate that GPX file generated from lowrance-all.usr
# when converted back to USR v2 matches previous executions of GPSBabel.
#
-# lowrance-ignoreicons.usr USR version 2 format file.
+# lowrance-ignoreicons.usr USR version 2 format file.
# Used to validate use of ignoreicons option to strip out Event Marker Icons.
#
# lowrance-v2.usr USR version 2 format file. Generated on an unknown Lowrance unit.
# Each trail is named 'Trail 1'.
# The first 'Trail 1' has 2000 points boken into 10 sections with 200 points
# in each section. The second 'Trail 1' has 1258 points broken into 7 sections,
-# with 200 points in 6 and 58 in the last.
+# with 200 points in 6 and 58 in the last.
#
# lowrance-v2-unicsv.txt Comma seperated file generated from lowrance-v2.usr by GPSBabel.
# Used to validate that the parsing of the USR version 2 file yields the same
# Test ability to read non-Lowrance format and generate USR v2 file
gpsbabel -i geo -f ${REFERENCE}/../geocaching.loc -o lowranceusr,wversion=2 -F ${TMPDIR}/lowrance1.usr
-bincompare ${TMPDIR}/lowrance1.usr ${REFERENCE}/lowrance.usr
+bincompare ${REFERENCE}/lowrance.usr ${TMPDIR}/lowrance1.usr
# Use the file just created to see if can write back the same data
-gpsbabel -i lowranceusr -f ${TMPDIR}/lowrance1.usr -o lowranceusr,wversion=2 -F ${TMPDIR}/lowrance1.usr
-# Unfortunately precision issues cause mismatch on Lat/Long conversion, actual test validation commented out
-# bincompare ${REFERENCE}/lowrance.usr ${TMPDIR}/lowrance1.usr
+gpsbabel -i lowranceusr -f ${TMPDIR}/lowrance1.usr -o lowranceusr,wversion=2 -F ${TMPDIR}/lowrance2.usr
+# At a minimum unknown altitude not making the round trip, actual test validation commented out
+# bincompare ${REFERENCE}/lowrance.usr ${TMPDIR}/lowrance2.usr
# Test ability to generate GPX from USR v2 and then generate USR v2 using that newly created GPX file
gpsbabel -i lowranceusr -f ${REFERENCE}/lowrance-all.usr -o gpx,elevprec=6 -F ${TMPDIR}/lowrance-enchilada.gpx
-gpsbabel -i gpx -f ${TMPDIR}/lowrance-enchilada.gpx -o lowranceusr,wversion=2 -F ${TMPDIR}/lowrance-enchilada1.usr
-bincompare ${TMPDIR}/lowrance-enchilada1.usr ${REFERENCE}/lowrance-enchilada.usr
+gpsbabel -i gpx -f ${TMPDIR}/lowrance-enchilada.gpx -o lowranceusr,wversion=2 -F ${TMPDIR}/lowrance-enchilada.usr
+bincompare ${REFERENCE}/lowrance-enchilada.usr ${TMPDIR}/lowrance-enchilada.usr
# Don't convert icons as waypts
gpsbabel -i lowranceusr,ignoreicons -f ${REFERENCE}/lowrance-all.usr -o gpx,elevprec=6 -F ${TMPDIR}/lowrance-enchilada.gpx
-gpsbabel -i gpx -f ${TMPDIR}/lowrance-enchilada.gpx -o lowranceusr,wversion=2 -F ${TMPDIR}/lowrance-enchilada1.usr
-bincompare ${TMPDIR}/lowrance-enchilada1.usr ${REFERENCE}/lowrance-ignoreicons.usr
+gpsbabel -i gpx -f ${TMPDIR}/lowrance-enchilada.gpx -o lowranceusr,wversion=2 -F ${TMPDIR}/lowrance-ignoreicons.usr
+bincompare ${REFERENCE}/lowrance-ignoreicons.usr ${TMPDIR}/lowrance-ignoreicons.usr
#
# Another variation of Lowrance. Compare v2 and v3. These reference
#
# ${REFERENCE}/lowrance-hook2-v2.usr, ${REFERENCE}/lowrance-hook2-v3.usr,
-# ${REFERENCE}/lowrance-hook2-v4.usr, ${REFERENCE}/lowrance-hook2-v5.usr, ${REFERENCE}/lowrance-hook2-v6.usr
+# ${REFERENCE}/lowrance-hook2-v4.usr, ${REFERENCE}/lowrance-hook2-v5.usr, ${REFERENCE}/lowrance-hook2-v6.usr
# AND ${REFERENCE}/lowrance-hook2.gpx were generated on a single Lowrance Hook2 System.
# This system has the ability to select any one of those formats for database export.
# All files should contain the same basic data with increasing amounts of detail as you
gpsbabel -i lowranceusr -f ${REFERENCE}/lowrance-v4.usr -o gpx -F ${TMPDIR}/lowrance-v4.gpx
compare ${REFERENCE}/lowrance-v4.gpx ${TMPDIR}/lowrance-v4.gpx
+gpsbabel -i gpx -f ${TMPDIR}/lowrance-v4.gpx -o lowranceusr,wversion=4 -F ${TMPDIR}/lowrance-v4.usr
+gpsbabel -i lowranceusr -f ${TMPDIR}/lowrance-v4.usr -o gpx -F ${TMPDIR}/lowrance-v4~usr.gpx
+compare ${TMPDIR}/lowrance-v4.gpx ${TMPDIR}/lowrance-v4~usr.gpx
+
#
# Perform USR version 5 test
# -------------